package WhiskeyGui;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

/**
 * User: Mike
 * Date: 5/13/12
 */

public class DataCache {
//    public static ArrayList<Double> tempAFArr = new ArrayList<Double>();
//    public static ArrayList<Double> tempTFArr = new ArrayList<Double>();
//    private ArrayList<Double> timeS = new ArrayList<Double>();
//    private ArrayList<Double> distTemp = new ArrayList<Double>();
//    private ArrayList<String> dateTime = new ArrayList<String>();

    private ArrayList<Double> columnC;
    private ArrayList<Double> tempACArr;
    private ArrayList<Double> kalmanCArr;
    private ArrayList<Double> milliTimeArr;
    private ArrayList<Double> boilerTemp;

    private ArrayList<Double> corrAbvTime;
    private ArrayList<Double> corrAbv;
    private ArrayList<Double> vaporAbvCorr;
    private ArrayList<Double> vaporAbv;
    private ArrayList<Integer> bottleNum;
    private ArrayList<Double> rateByJar;
    private ArrayList<Double> bottleVol;
    private Hashtable<String, Double> bottleAbv;

    private ArrayList<Double> averageAbv;


    private BottleCalcs bottleCalcs;
    private static long endTime = 0;
    private String timeSpan;
    private String filePathName;
    private Map<String, String> timeSpanMap = new HashMap<String, String>();



    public DataCache(String filePathName) {
        this.filePathName = filePathName;

        bottleCalcs = new BottleCalcs();

        tempACArr = new ArrayList<Double>();
        columnC = new ArrayList<Double>();
        kalmanCArr = new ArrayList<Double>();
        milliTimeArr = new ArrayList<Double>();
        boilerTemp = new ArrayList<Double>();
        corrAbv = new ArrayList<Double>();
        corrAbvTime = new ArrayList<Double>();
        vaporAbvCorr = new ArrayList<Double>();
        vaporAbv = new ArrayList<Double>();
        bottleNum = new ArrayList<Integer>();
        averageAbv = new ArrayList<Double>();


        rateByJar = new ArrayList<Double>();
        bottleVol = new ArrayList<Double>();
        bottleAbv = new Hashtable<String, Double>();
        initializeTimeSpanMap();
     }

     private void initializeTimeSpanMap() {
         timeSpanMap.put("5 min", "5"); //adding value to Hashtable
         timeSpanMap.put("10 min", "10");
         timeSpanMap.put("20 min", "20");
         timeSpanMap.put("30 min", "30");
         timeSpanMap.put("45 min", "45");
         timeSpanMap.put("1 hr", "60");
         timeSpanMap.put("2 hr", "120");
         timeSpanMap.put("5 hr", "300");
         timeSpanMap.put("10 hr", "600");
         timeSpanMap.put("1 day", "1440");
         timeSpanMap.put("2 days", "2880");
         timeSpanMap.put("3 days", "4320");
         timeSpanMap.put("4 days", "5760");
         timeSpanMap.put("5 days", "7200");
         timeSpanMap.put("6 days", "8640");
         timeSpanMap.put("7 days", "10080");
         timeSpanMap.put("8 days", "11520");
         timeSpanMap.put("10 days", "14400");
         timeSpanMap.put("30 days", "43200");
     }





    public void Update() {
        BufferedReader readbuffer = null;

        try {
            readbuffer = new BufferedReader(new FileReader(filePathName));      //	"" + DatFile.Path[DatFile.Index] + "\\" + DatFile.Name[DatFile.Index]));
        } catch (FileNotFoundException e1) {
            System.out.println("File not found: " + filePathName);
            System.out.println("Cannot display data, none recorded yet.");

//            e1.printStackTrace();
        }
        String strRead;
        long startReadHere = 0;
        int i = 0;                         // where we are in the file
        int k = 0;                         // index to import next set of data aquisition initialization
        int lastRecordedBottleNum = 0;

        long totalMin = CountData();
        if (totalMin > Long.valueOf(getTimeSpanHash())) {
            startReadHere = (endTime - 60 * 1000 * Long.valueOf(getTimeSpanHash()));
        }
        try {
            if (readbuffer != null)
                while ((strRead = readbuffer.readLine()) != null) {
                    String splitarray[] = strRead.split("\t");
                    if (k == 0) {        // header
                        cleanUpArrays();
                    }
                    if (k >= 1 && Double.parseDouble(splitarray[1].trim()) >= startReadHere && splitarray.length >= 8) {
                        milliTimeArr.add(Double.parseDouble(splitarray[1].trim()));
                        if (splitarray.length >= 2)
                            kalmanCArr.add(Double.parseDouble(splitarray[2].trim()));
                        if (splitarray.length >= 3)
                            columnC.add(Double.parseDouble(splitarray[3].trim()));
                        if (splitarray.length >= 5)
                            tempACArr.add(Double.parseDouble(splitarray[5].trim()));
                        if (splitarray.length >= 7)
                            bottleNum.add(Integer.parseInt(splitarray[7].trim()));
                        if (splitarray.length >= 8) {
                            double correctedAbv = Double.parseDouble(splitarray[8].trim());
                            if (corrAbv.size() >= 1 && correctedAbv != corrAbv.get(corrAbv.size() - 1)) {           // only read it in if it is the first or it has changed
                                corrAbv.add(correctedAbv);
                                corrAbvTime.add(milliTimeArr.get(milliTimeArr.size() - 1));
                            } else if (corrAbv.size() == 0 && correctedAbv > 5.0) {
                                corrAbv.add(correctedAbv);
                                corrAbvTime.add(milliTimeArr.get(milliTimeArr.size() - 1));
                            }
                        }
                        if (splitarray.length >= 9)
                            vaporAbv.add(Double.parseDouble(splitarray[9].trim()));
                        if (splitarray.length >= 11)
                            boilerTemp.add(Double.parseDouble(splitarray[11].trim()));
//                                if (splitarray.length >= 12)
//                                    rateByRate.add(Double.parseDouble(splitarray[12].trim()));
                        if (splitarray.length >= 13)
                            rateByJar.add(Double.parseDouble(splitarray[13].trim()));
                        if (splitarray.length >= 15)
                            bottleVol.add(Double.parseDouble(splitarray[15].trim()));
                        if (splitarray.length >= 19)
                            vaporAbvCorr.add(Double.parseDouble(splitarray[19].trim()));

                        if (lastRecordedBottleNum != bottleNum.get(bottleNum.size() - 1)) {
                            averageAbv.add(vaporAbvCorr.get(bottleNum.size() - 1));
                            int bottle = bottleNum.get(bottleNum.size() - 1);
                            double rate = rateByJar.get(bottleNum.size() - 1);
                            double abv = 0.;
                            double volume = bottleVol.get(bottleNum.size() - 1);
                            for (Double abvArr : averageAbv) {
                                abv = abv + abvArr;
                            }
                            abv = abv / averageAbv.size();
                            bottleCalcs.newBottle(bottle, rate, abv, volume);
                            averageAbv.clear();
                        } else {
                            averageAbv.add(vaporAbvCorr.get(bottleNum.size() - 1));
                        }

                        if (bottleAbv.size() == 0) {
//                                bottleAbv.put(String.valueOf(bottleNum.get(bottleNum.size() - 1)), corrAbv.get(corrAbv.size()-1));
                            bottleAbv.put(String.valueOf(lastRecordedBottleNum + 1), vaporAbvCorr.get(vaporAbvCorr.size() - 1));
                            lastRecordedBottleNum = bottleNum.get(bottleNum.size() - 1);
                        }

                        // if the bottleNum num has changed by 2, record the previous bottleNum corrAbv
                        if (bottleNum.size() > 1 && bottleNum.get(bottleNum.size() - 1) - lastRecordedBottleNum == 3) {
                            Double changeAbv = vaporAbvCorr.get(vaporAbvCorr.size() - 1) - bottleAbv.get(String.valueOf(lastRecordedBottleNum));
                            changeAbv = bottleAbv.get(String.valueOf(lastRecordedBottleNum)) + changeAbv / 3.;
                            bottleAbv.put(String.valueOf(lastRecordedBottleNum + 1), changeAbv);
                            lastRecordedBottleNum++;
                        }

                        // if the bottleNum num has changed by 2, record the previous bottleNum corrAbv
                        if (bottleNum.size() > 1 && bottleNum.get(bottleNum.size() - 1) - lastRecordedBottleNum == 2) {
                            Double changeAbv = vaporAbvCorr.get(vaporAbvCorr.size() - 1) - bottleAbv.get(String.valueOf(lastRecordedBottleNum - 1));
                            changeAbv = bottleAbv.get(String.valueOf(lastRecordedBottleNum)) + changeAbv / 2.;
                            bottleAbv.put(String.valueOf(lastRecordedBottleNum + 1), changeAbv);
                            lastRecordedBottleNum++;
                        }

                        // if the bottleNum num has changed by 1, record new bottleNum corrAbv
                        if (bottleNum.size() > 1 && bottleNum.get(bottleNum.size() - 1) - lastRecordedBottleNum == 1) {
                            bottleAbv.put(String.valueOf(lastRecordedBottleNum + 1), vaporAbvCorr.get(vaporAbvCorr.size() - 1));
                            lastRecordedBottleNum = bottleNum.get(bottleNum.size() - 1);
                        }
                        //                        distTemp.add(Double.parseDouble(splitarray[10].trim()));
                        //                        tempAFArr.add(Double.parseDouble(splitarray[6].trim()));
                        //                        tempTFArr.add(Double.parseDouble(splitarray[4].trim()));
                        //                        timeS.add(Double.parseDouble(splitarray[2].trim()));
                        //                        dateTime.add(splitarray[0].trim());
                    }
                    k = k + 1;
                    i = i + 1;
                }
            if (readbuffer != null)
                readbuffer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static long CountData() {
        System.out.println("Reading in DAT file....");                                    // import data from file (DatFile.Index), line by line (i), into arrays (j)
        BufferedReader readbuffer = null;
        String filePathName = "C:\\WhiskeyData\\output.txt";
        try {

            readbuffer = new BufferedReader(new FileReader(filePathName));
        } catch (FileNotFoundException e1) {
            System.out.println("File not found:" + filePathName);
            System.out.println("Cannot display data, none found yet.");
        }
        String strRead;
        int i = 0;                         // where we are in the file
        int k = 0;                         // index to import next set of data acquisition initialization
        long initialMin = 0;
        long totalMin = 0;
        boolean firstLine = true;
        try {
            if (readbuffer != null)
                while ((strRead = readbuffer.readLine()) != null) {
                    String splitarray[] = strRead.split("\t");
                    if (k == 0) {       // header
                    }
                    if (k > 0) {        // read in data
                        if (splitarray.length >= 12) {                         // check to make sure there is data there
                            if (firstLine) {
                                firstLine = false;
                                initialMin = (long) Double.parseDouble(splitarray[1].trim());
                            }
                            endTime = (long) Double.parseDouble(splitarray[1].trim());
                        }
                    }
                    k = k + 1;
                    i = i + 1;
                }
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        try {
            if (readbuffer != null)
                readbuffer.close();
        }                         //Close the stream to free memory resources on the host computer:
        catch (IOException e1) {
            e1.printStackTrace();
        }

        System.out.println("totalMin readin = " + totalMin);
        totalMin = (endTime - initialMin) / 1000 / 60;
        System.out.println("totalMin readin = " + totalMin);
        return totalMin;
    }

    private void cleanUpArrays() {
        columnC.clear();
        tempACArr.clear();
        kalmanCArr.clear();
        milliTimeArr.clear();
        boilerTemp.clear();
        corrAbv.clear();
        corrAbvTime.clear();
        vaporAbvCorr.clear();
        vaporAbv.clear();
        bottleNum.clear();
        rateByJar.clear();
        bottleVol.clear();
        bottleAbv.clear();
//                        abvUncorr.clear();
//                        distTemp.clear();
//                        dateTime.clear();
//                        timeS.clear();
//                        tempTFArr.clear();
//                        tempAFArr.clear();
    }

    public ArrayList<Double> getVaporAbv() {
        return vaporAbv;
    }

    public ArrayList<Double> getVaporAbvCorr() {
        return vaporAbvCorr;
    }

    public Hashtable<String, Double> getBottleAbv() {
        return bottleAbv;
    }

    public ArrayList<Double> getColumnC() {
        return columnC;
    }

    public ArrayList<Double> getKalmanCArr() {
        return kalmanCArr;
    }

    public ArrayList<Double> getmilliTime() {
        return milliTimeArr;
    }

    public void setTimeSpan(String timeSpan) {
        this.timeSpan = timeSpan;
    }

    public String getTimeSpan() {
        return timeSpan;
    }

    public ArrayList<Double> getCorrAbvTime() {
        return corrAbvTime;
    }

    public ArrayList<Double> getCorrAbv() {
        return corrAbv;
    }

    public ArrayList<Double> getBottleVol() {
        return bottleVol;
    }

    public ArrayList<Double> getAverageAbv() {
        return averageAbv;
    }

    public BottleCalcs getBottleCalcs() {
        return bottleCalcs;
    }

    private String getTimeSpanHash() {
          return timeSpanMap.get(timeSpan);
      }


        //    private void convertTime(int milliTime) {
//        SimpleDateFormat sdf = new SimpleDateFormat("MMM dd,yyyy HH:mm");
//        Date resultdate = new Date(milliTime);
//        System.out.println(sdf.format(resultdate));
//    }

}

